﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace THO7_Team8
{
    public static class Utils
    {
        //To grayscale
        /// <summary>
        /// 
        /// </summary>
        /// <param name="picture">Bitmap to be converted to grayscale</param>
        /// <returns>A grayscale version of the provided bitmap.</returns>
        public static Bitmap toGrayScale(Bitmap picture)
        {
            UnsafeBitmap ubmp = new UnsafeBitmap(picture);
            ubmp.LockBitmap();

            for (int y = 0; y < picture.Height; y++)
            {
                for (int x = 0; x < picture.Width; x++)
                {
                    PixelData pd = ubmp.GetPixel(x, y);
                    int newColor = (int)((pd.red * 0.3) + (pd.green * 0.59) + (pd.blue * 0.11));
                    pd.red = (byte)newColor;
                    pd.green = (byte)newColor;
                    pd.blue = (byte)newColor;

                    ubmp.SetPixel(x, y, pd);
                }
            }

            ubmp.UnlockBitmap();

            return ubmp.Bitmap;
        }

        //Threshold
        public static Bitmap toBinary(Bitmap picture, byte threshold)
        {
            UnsafeBitmap ubmp = new UnsafeBitmap(picture);
            ubmp.LockBitmap();

            for (int y = 0; y < picture.Height; y++)
            {
                for (int x = 0; x < picture.Width; x++)
                {
                    PixelData pd = ubmp.GetPixel(x, y);
                    byte newColor = 255;
                    if (pd.red < threshold)
                    {
                        newColor = 0;
                    }

                    pd.red = (byte)newColor;
                    pd.green = (byte)newColor;
                    pd.blue = (byte)newColor;

                    ubmp.SetPixel(x, y, pd);
                }
            }

            ubmp.UnlockBitmap();

            return ubmp.Bitmap;
        }

         /// <summary>
         /// Converts hue, saturation and value to RGB.
         /// </summary>
         /// <param name="h">The hue</param>
         /// <param name="s">The saturation</param>
         /// <param name="v">The value</param>
         /// <returns></returns>
        public static PixelData hsvToRgb(double h, double s, double v)
        {
            double R, G, B;

            if (v <= 0)
            {
                R = G = B = 0;
            }
            else if (s <= 0)
            {
                R = G = B = v;
            }
            else
            {
                double hf = h / 60.0;
                int i = (int)Math.Floor(hf);
                double f = hf - i;
                double pv = v * (1 - s);
                double qv = v * (1 - s * f);
                double tv = v * (1 - s * (1 - f));
                switch (i)
                {

                    // Red is the dominant color
                    case 0:
                        R = v;
                        G = tv;
                        B = pv;
                        break;

                    // Green is the dominant color
                    case 1:
                        R = qv;
                        G = v;
                        B = pv;
                        break;
                    case 2:
                        R = pv;
                        G = v;
                        B = tv;
                        break;

                    // Blue is the dominant color
                    case 3:
                        R = pv;
                        G = qv;
                        B = v;
                        break;
                    case 4:
                        R = tv;
                        G = pv;
                        B = v;
                        break;

                    // Red is the dominant color
                    case 5:
                        R = v;
                        G = pv;
                        B = qv;
                        break;

                    default:
                        R = G = B = v; // Just pretend its black/white
                        break;
                }
            }
            PixelData pd = new PixelData();

            pd.red = (byte)minMaxNumber((int)(R * 255.0));
            pd.green = (byte)minMaxNumber((int)(G * 255.0));
            pd.blue = (byte)minMaxNumber((int)(B * 255.0));

            return pd;
        }
        /// <summary>
        /// Checks whether the provided number is between 0 and 255. If not, the maximum/minimum value is returned.
        /// </summary>
        /// <param name="i">Number to check</param>
        /// <returns></returns>
        private static int minMaxNumber(int i)
        {
            if (i < 0) return 0;
            if (i > 255) return 255;
            return i;
        }


        /// <summary>
        /// Copy a bitmap to a new bitmap with the provided dimensions.
        /// </summary>
        /// <param name="srcBitmap">Bitmap to copy</param>
        /// <param name="section">Dimensions to draw the bitmap on</param>
        /// <returns>A bitmap with the provided dimensions.</returns>
        static public Bitmap bitmapCopy(Bitmap srcBitmap, Rectangle section)
        {
            // Create the new bitmap and associated graphics object
            Bitmap bmp = new Bitmap(section.Width, section.Height);
            Graphics g = Graphics.FromImage(bmp);

            // Draw the specified section of the source bitmap to the new one
            g.DrawImage(srcBitmap, 0, 0, section, GraphicsUnit.Pixel);

            // Clean up
            g.Dispose();

            // Return the bitmap
            return bmp;
        }

    }
}
